#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2023/12/11 22:02
# @Author  : FuKai ZHANG
# @File    : request_control.py
# @Description :request封装
import os
import requests
from typing import Dict
from utils.logging_tools.log_decorator import log_decorator
from utils.models.models import TestCase, CaseCompleteParams
from config.global_config import config
from utils.request_tools.case_run_time_decorator import execution_duration
from utils.variable_handling.json_extract import JsonPathExtractor
from utils.variable_handling.relpace_variable import VariableReplacer
from utils.models.models import RequestType


class RequestControl:
    def __init__(self, case_data: Dict):
        """case_data 是从用例池中拿出来 经过@pytest.mark.parametrize 传递过的字典"""
        # 先进行变量替换
        new_case_data=VariableReplacer.replace_variables(data=case_data)
        self.__yaml_case = TestCase(**new_case_data)  # 解包
        # url拼接hosts
        self._url = config.host + self.__yaml_case.url

    # 处理requestType为json格式
    def request_type_for_json(self, **kwargs):
        """ 判断请求类型为json格式，这里暂时没有处理json里面有中文的情况 """
        res = requests.request(
            method=self.__yaml_case.method,
            url=self._url,
            json=self.__yaml_case.data,
            headers=self.__yaml_case.headers,
            verify=False,
            **kwargs
        )
        return res

    # 需要URL参数拼接
    def url_params(self):
        """url拼接params """
        _data = self.__yaml_case.data
        params_data = "?"
        if _data is not None:
            # url 拼接的方式传参,?后面拼接参数
            for key, value in _data.items():
                if value is None or value == '':
                    params_data += (key + "&")
                else:
                    params_data += (key + "=" + str(value) + "&")
        return params_data[:-1]

    # 处理requestType是params，
    def request_type_for_params(self):
        res = requests.request(
            method=self.__yaml_case.method,
            url=self._url,
            params=self.__yaml_case.data,
            headers=self.__yaml_case.headers,
            verify=False,
        )
        return res

    def request_type_for_file(self):
        """这里仅做png图片上传的适配，其他文件的适配根据需要哦修改"""
        file_path = self.__yaml_case.data.file_path
        with open(file_path, 'rb') as image_file:
            files = {
                'avatar_image': (os.path.basename(file_path), image_file, 'image/png')  # 假设是 PNG，根据实际图片调整 MIME
            }
        data = self.__yaml_case.data.file_date
        res = requests.request(
            method=self.__yaml_case.method,
            url=self._url,
            files=files,
            verify=False,
            data=data,
        )
        return res

    # 处理requestType为form格式
    def request_type_for_form(self, **kwargs):
        """ 处理requestType为form格式 """
        res = requests.request(
            method=self.__yaml_case.method,
            url=self._url,
            data=self.__yaml_case.data,
            headers=self.__yaml_case.headers,
            verify=False,
            **kwargs
        )
        return res

    # 处理无参数请求，如导出接口
    def request_type_for_export(self, **kwargs):
        """ 处理导出等无参数请求 """
        res = requests.request(
            method=self.__yaml_case.method,
            url=self._url,
            headers=self.__yaml_case.headers,
            verify=False,
            **kwargs
        )
        return res

    # 获取接口的响应时长
    @classmethod
    def response_elapsed_total_seconds(cls, res) -> float:
        """获取接口响应时长"""
        try:
            return round(res.elapsed.total_seconds() * 1000, 2)
        except AttributeError:
            return 0.00

    """这里需要整理一条case所有完整的参数，包括响应和请求，方便后续统计错误用例，打印日志使用,断言等使用"""

    def check_response_data(self, res):
        """先判断请求方式，get请求直接打印url，其他请求返回响应结果"""

        if self.__yaml_case.method == "get":
            return res.url
        else:
            return res.text #返回字符串


    def check_case_complete_params(self, response) -> CaseCompleteParams:
        """这里目前只写了这么多参数，后续有需要再修改"""
        # 提取变量
        
        _data = {
            "url": self.__yaml_case.url,
            "detail": self.__yaml_case.detail,
            "request_headers": self.__yaml_case.headers,
            "request_data": self.__yaml_case.data,
            "method": self.__yaml_case.method,
            "expected": self.__yaml_case.expected,
            "extract": self.__yaml_case.extract,
            "status_code": response.status_code,
            "response_headers": response.headers,
            "response_data": self.check_response_data(response),  # get请求打印url,其他请求返回字符串
            "response_time": self.response_elapsed_total_seconds(response)
        }
        return CaseCompleteParams(**_data)

    """
    发送请求
    1.打印日志
    2.为每个接口设置一个最大等待时长
    3.统一整合一条case所有的数据
    """

    # @execution_duration(number=3000)  # 请求时长控制，单位毫秒，超过时长打印错误日志
    # @log_decorator(switch=True)  # 打印日志
    def send_http_request(self):
        """通过字典的get(key)方法，匹配到对应的requestType函数"""

        # 定义一个字典，用于映射requestType
        requests_type_mapping = {
            RequestType.JSON.value: self.request_type_for_json,
            RequestType.PARAMS.value: self.request_type_for_params,
            RequestType.FILE.value: self.request_type_for_file,
            RequestType.FORM.value: self.request_type_for_form,
            RequestType.EXPORT.value: self.request_type_for_export,
        }

        # 调用mapping里的函数
        res = requests_type_mapping.get(self.__yaml_case.requestType)()
        case = self.check_case_complete_params(response=res)
        # 提取变量
        JsonPathExtractor.extract(response_data=case.response_data, extract_rules=case.extract)
        return case
